﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using MahApps.Metro.Controls;
using Reader.Libs.PDF;
using Reader.Libs.HTML;
using Reader.Libs.DOCX;
using System.Windows.Markup;
using System.Diagnostics;
using Reader.Libs.PRC;
using iTextSharp.text.pdf;
using Reader.Libs.PDF.Helper;
using MahApps.Metro;
using Reader.Libs.BOOKOBJ;
using Reader.UC.Dialogs;
using Reader.Libs.CONVERTER;

namespace Reader
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : MetroWindow
    {
        MainWindowDataContext _context;
        private int RDIndex = 1;
        private string lastFilePath = "";
        public MainWindow()
        {
            _context = new MainWindowDataContext();
            this.DataContext = _context;
            InitializeComponent();
            Application.Current.Resources["GlowColor"] = ((SolidColorBrush)FindResource("AccentColorBrush")).Color;
            this.Menu.OnMenuBtn_Click += OnMenuButton_Click;
            ThemeManager.IsThemeChanged += ThemeManager_IsThemeChanged;

            this.pdfPanel.OnOpenFly += OnOpenFly;
            this.MainReaderUC.OnOpenFly += OnOpenFly;
            this.lidUC.OnOpenFly += OnOpenFly;

            this.lidUC.OnReadBook += lidUC_OnReadBook;

        }

        void lidUC_OnReadBook(object sender, EventArgs e)
        {
            try
            {
                if (this.lidUC.LibListBox.SelectedItems.Count > 0)
                {
                    Book b = this.lidUC.LibListBox.SelectedItems[0] as Book;

                    if (System.IO.File.Exists(b.FilePath))
                        LoadBook(b.FilePath);
                }
            }
            catch (System.Exception ex)
            {
                MessageBox.Show("Error! " + ex.Message);
            }
        }

        void OnOpenFly(object sender, EventArgs e)
        {
            this.MenuFlyOut.IsOpen = !this.MenuFlyOut.IsOpen;
        }

        void OnBackLib(object sender, EventArgs e)
        {
            this.MenuFlyOut.IsOpen = false;
            this.MainTab.SelectedIndex = 0;
        }

        private void ThemeManager_IsThemeChanged(object sender, OnThemeChangedEventArgs e)
        {
            Application.Current.Resources["GlowColor"] = ((SolidColorBrush)FindResource("AccentColorBrush")).Color;
        }

        private void OnMenuButton_Click(object sender, EventArgs e)
        {
            try
            {
                Button b = sender as Button;
                switch (b.Name)
                {
                    case "ReadingBtn":
                        this.MainTab.SelectedIndex = RDIndex;
                        break;
                    case "LibraryBtn":
                        this.MainTab.SelectedIndex = 0;
                        break;
                    case "OpenBtn":
                        MenuOpen_Click();
                        break;
                    case "ConvertBtn":
                        OpenConvertDialog();
                        break;
                }
                if (this.MenuFlyOut.IsOpen)
                    this.MenuFlyOut.IsOpen = !this.MenuFlyOut.IsOpen;
            }
            catch
            {
                MessageBox.Show("Error!");
            }
        }

        private void OpenConvertDialog()
        {
            try
            {
                this.MenuFlyOut.IsOpen = false;
                ConvertDialog dg;
                if (this.lidUC.LibListBox.SelectedItems.Count > 0)
                {
                    Book book = (from b in this.lidUC.booklib.BookList
                                 where b == (this.lidUC.LibListBox.SelectedItems[0] as Book)
                                 select b).First();
                    dg = new ConvertDialog(book);
                }
                else
                {
                    dg = new ConvertDialog(null);
                }
                dg.ShowDialog();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error! \n" + ex.Message);
            }
        }
        private void MenuOpen_Click()
        {
            try
            {
                Microsoft.Win32.OpenFileDialog OfDlg = new Microsoft.Win32.OpenFileDialog();
                OfDlg.Filter = "Ebook files |*.txt; *.pdf; *.html; *.htm; *.doc; *.docx; *.mobi; *.prc" +
                               "|PDF File |*.pdf" + "|Web Page |*.html; *.htm" +
                               "|Word File |*.doc; *.docx" + "|MobiPocKet |*.prc; *.mobi";
                OfDlg.Multiselect = false;
                OfDlg.ShowDialog();
                LoadBook(OfDlg.FileName);
            }
            catch (System.Exception ex)
            {
                MessageBox.Show("Error! " + ex.Message);
            }
        }

        public void LoadBook(string fileDir)
        {
            try
            {
                if (this.lastFilePath == fileDir)
                {
                    this.MainTab.SelectedIndex = RDIndex;
                    return;
                }

                string fileExt = System.IO.Path.GetExtension(fileDir);

                if (fileExt.Equals(".pdf"))
                {
                    this.RDIndex = 1;
                    LoadPdf(fileDir);
                }
                else
                {
                    this.RDIndex = 2;
                    if (fileExt.Equals(".txt"))
                    {
                        LoadTxt(fileDir);
                    }

                    if (fileExt.Equals(".htm") || fileExt.Equals(".html"))
                    {
                        LoadHtml(fileDir);
                    }

                    if (fileExt.Equals(".docx"))
                    {
                        LoadDocX(fileDir);
                    }

                    if (fileExt.Equals(".doc"))
                    {
                        LoadDoc(fileDir);
                    }

                    if (fileExt.Equals(".mobi") || fileExt.Equals(".prc"))
                    {
                        LoadPrc(fileDir);
                    }
                }

                this.MainTab.SelectedIndex = RDIndex;
                this.lastFilePath = fileDir;
            }
            catch { throw; }
        }

        private void LoadTxt(string fileDir)
        {
            string sb = "";
            try
            {
                using (FileStream fs = File.Open(fileDir, FileMode.Open, FileAccess.ReadWrite))
                using (BufferedStream bs = new BufferedStream(fs))
                using (StreamReader sr = new StreamReader(bs))
                {
                    sb = sr.ReadToEnd();
                }
                GC.Collect();
            }
            catch (IOException ex)
            {
                MessageBox.Show("Error Open File: \n"+ex.Message, "IO Error", MessageBoxButton.OK);
            }
            
            sb = sb.Replace("\r\n", "\n");
            sb = sb.Replace("\n\n\n", "\n");
            sb = sb.Replace("\n\n", "\n");

            string[] sa = sb.Split('\n');
            FlowDocument fd = new FlowDocument();
            fd.ColumnGap = 40;
            fd.ColumnWidth = 500;
            foreach (string s in sa)
            {
                if (s.Length > 2)
                    fd.Blocks.Add(new Paragraph(new Run(s)));
            } 
            this.MainReaderUC.DocViewer.Document = fd;
        }

        private void LoadDocX(string fileDir)
        {
            try
            {
                FlowDocument fd = new FlowDocument();
                fd.FontFamily = new FontFamily("Times New Roman");
                fd.ColumnGap = 40;
                fd.ColumnWidth = 500;
                fd.LoadFromWordML(fileDir);
                this.MainReaderUC.DocViewer.Document = fd;
//                 IConverter doc = ConverterLocator.Converter(fileDir, "C://new.pdf");
//                 string s = doc.Convert().ToString();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error Open File: \n" + ex.Message, "IO Error", MessageBoxButton.OK);
            }
        }

        private void LoadDoc(string fileDir)
        {
            try
            {
                if (!System.IO.Directory.Exists("C://tmp"))
                    System.IO.Directory.CreateDirectory("C://tmp");
                else
                {
                    foreach (FileInfo f in (new DirectoryInfo("C://tmp")).GetFiles())
                        f.Delete();
                    foreach (DirectoryInfo dir in (new DirectoryInfo("C://tmp")).GetDirectories())
                    {
                        dir.Delete(true);
                    }
                }
                DocConverter docCovt = new DocConverter();
                docCovt.ConvertToDocX(fileDir, "C://tmp//tmp.docx");

                LoadDocX("C://tmp//tmp.docx");
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error Open File: \n" + ex.Message, "IO Error", MessageBoxButton.OK);
            }
        }

        private void LoadHtml(string fileDir)
        {
            string sb = "";
            try
            {
                using (FileStream fs = File.Open(fileDir, FileMode.Open, FileAccess.ReadWrite))
                using (BufferedStream bs = new BufferedStream(fs))
                using (StreamReader sr = new StreamReader(bs))
                {
                    sb = sr.ReadToEnd();
                }
                GC.Collect();
            }
            catch (IOException ex)
            {
                MessageBox.Show("Error Open File: \n" + ex.Message, "IO Error", MessageBoxButton.OK);
            }


            var xaml = HtmlToXamlConverter.ConvertHtmlToXaml(sb.ToString(), true);
            var flowDocument = XamlReader.Parse(xaml);
            if (flowDocument is FlowDocument)
                SubscribeToAllHyperlinks((FlowDocument)flowDocument);

            FlowDocument fd = (FlowDocument)flowDocument;
            fd.ColumnGap = 40;
            fd.ColumnWidth = 500;
            
            this.MainReaderUC.DocViewer.Document = fd;
        }

        private void SubscribeToAllHyperlinks(FlowDocument flowDocument)
        {
            var hyperlinks = GetVisuals(flowDocument).OfType<Hyperlink>();
            foreach (var link in hyperlinks)
                link.RequestNavigate += LinkRequestNavigate;
        }

        private static IEnumerable<DependencyObject> GetVisuals(DependencyObject root)
        {
            foreach (var child in
               LogicalTreeHelper.GetChildren(root).OfType<DependencyObject>())
            {
                yield return child;
                foreach (var descendants in GetVisuals(child))
                    yield return descendants;
            }
        }

        private void LinkRequestNavigate(object sender,
          System.Windows.Navigation.RequestNavigateEventArgs e)
        {
            Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
            e.Handled = true;
        }

        private void LoadPrc(string fileDir)
        {
            try
            {
                MobiDoc md = new MobiDoc();
                md.loadContent(fileDir);

                var xaml = HtmlToXamlConverter.ConvertHtmlToXaml(md.BookContent, true);
                var flowDocument = XamlReader.Parse(xaml);
                if (flowDocument is FlowDocument)
                    SubscribeToAllHyperlinks((FlowDocument)flowDocument);

                FlowDocument fd = (FlowDocument)flowDocument;
                fd.ColumnGap = 40;
                fd.ColumnWidth = 500;

                this.MainReaderUC.DocViewer.Document = fd;
            }
            catch (Exception)
            {
                
                throw;
            }
        }

        private void LoadPdf(string fileDir)
        {
            try
            {
                pdfPanel.OpenFile(fileDir);
                pdfPanel.PageRowDisplay = PageRowDisplayType.ContinuousPageRows;
            }
            catch (Exception ex)
            {
                MessageBox.Show(string.Format("An error occured: " + ex.Message));
            }
        }

        internal bool IsPdfLoaded()
        {
            return pdfPanel.CurrentSource != null;
        }

        private void SettingBtn_Click(object sender, RoutedEventArgs e)
        {
            (sender as Button).ContextMenu.IsEnabled = true;
            (sender as Button).ContextMenu.PlacementTarget = (sender as Button);
            (sender as Button).ContextMenu.Placement = System.Windows.Controls.Primitives.PlacementMode.Bottom;
            (sender as Button).ContextMenu.IsOpen = true;
        }

    }
}
